package com.heima.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.heima.common.dtos.PageResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;
import com.heima.common.util.BeanHelper;
import com.heima.common.util.JsonUtils;
import com.heima.model.admin.dtos.NewsAuthDto;
import com.heima.model.media.dtos.WmNewsDto;
import com.heima.model.media.dtos.WmNewsPageReqDto;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.wemedia.entity.WmMaterial;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.IWmMaterialService;
import com.heima.wemedia.service.IWmNewsMaterialService;
import com.heima.wemedia.service.IWmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.heima.common.constants.message.NewsAutoScanConstants.WM_NEWS_AUTO_SCAN_TOPIC;
import static com.heima.common.constants.message.WmNewsUpDownConstants.WM_NEWS_UP_OR_DOWN_TOPIC;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author heima
 * @since 2021-03-16
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements IWmNewsService {

    @Override
    public PageResult<WmNewsDto> findByPage(WmNewsPageReqDto dto) {
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //组装分页条件
        Page<WmNews> page = new Page<>(dto.getPage(),dto.getSize());
        //组装查询条件
        //1基于用户id查询
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getWmUserId,userId);
        //2基于文章状态查询
        if(dto.getStatus()!=null && dto.getStatus()!=-1){
            //审核通过
            if(dto.getStatus()==4){
                //自动审核通过 8 、人工审核通过 4 、已发布文章 9  status in(4,8,9)
                queryWrapper.lambda().in(WmNews::getStatus,new Integer[]{4,8,9});
            }else if(dto.getStatus()==1){//待审核
                //待人工审核 3 提交待审核 1
                queryWrapper.lambda().in(WmNews::getStatus,new Integer[]{1,3});
            }else{
                queryWrapper.lambda().eq(WmNews::getStatus,dto.getStatus());
            }
        }
        //3基于关键字条件 模糊频道title查询
        if(StringUtils.isNotBlank(dto.getKeyword())){
            queryWrapper.lambda().like(WmNews::getTitle,dto.getKeyword());
        }
        //4 基于频道条件查询
        if(dto.getChannelId()!=null){
            queryWrapper.lambda().eq(WmNews::getChannelId,dto.getChannelId());
        }
        //5 基于发布时间条件查询
        if(dto.getBeginPubDate()!=null){
            queryWrapper.lambda().ge(WmNews::getPublishTime,dto.getBeginPubDate());
        }
        if(dto.getEndPubDate()!=null){
            queryWrapper.lambda().le(WmNews::getPublishTime,dto.getEndPubDate());
        }
        //6 执行查询
        IPage<WmNews> iPage = this.page(page, queryWrapper);
        if(CollectionUtils.isEmpty(iPage.getRecords())){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章数据不存在");
        }
        //7 组装查询结果
        List<WmNewsDto> wmNewsDtoList = BeanHelper.copyWithCollection(iPage.getRecords(), WmNewsDto.class);

        return new PageResult<WmNewsDto>(dto.getPage(),dto.getSize(),iPage.getTotal(),wmNewsDtoList);
    }

    @Autowired
    private IWmNewsMaterialService wmNewsMaterialService;

    @Autowired
    private IWmMaterialService wmMaterialService;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Override
    @Transactional
    public void saveNews(WmNewsDto dto) {
        //1、获取用户id，判断登录状态
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2、数据转换
        WmNews wmNews = BeanHelper.copyProperties(dto, WmNews.class);
        //3、如果是保存操作，需要设置如下字段
        if(dto.getId()==null){
            wmNews.setCreatedTime(new Date());
            //关联自媒体用户id
            wmNews.setWmUserId(userId);
        }
        //如果不是保存草稿，需要设置提交时间
        if(!dto.getDraft()){
            wmNews.setSubmitedTime(new Date());
        }
        //处理封面图片 获取图片地址，通过逗号拼接
        List<String> imagesList = dto.getImages();
        if(!CollectionUtils.isEmpty(imagesList)){
            //流式编程，简化集合操作
            String images = imagesList.stream().collect(Collectors.joining(","));
            wmNews.setImages(images);
        }
        //保存或者修改文章
        boolean b = this.saveOrUpdate(wmNews);
        if(!b){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"保存或者修改文章失败");
        }
        //维护文章和素材的关联关系
        //如果是修改操作，先删除原有文章和素材的关联关系
        if(dto.getId()!=null){
            wmNewsMaterialService.deleteByNewsId(dto.getId());
        }
        //保存文章正文和素材关联关系
        //获取提交正文数据
        //[{"type":"text","value":"测试文章，很赞哦。不错。值得查阅"},{"type":"image","value":"https://javaee8.oss-cn-beijing.aliyuncs.com/c990c529-69d9-4b90-bc14-b43f07564035.jpg"}]
        String content = dto.getContent();
        //解析json格式数据   List<Map<String,String>>
        List<Map<String, String>> contentList = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, String>>>() {
        });
        //       从map对象中获取引用的素材图片url
        List<String> imageUrlList = parseImageUrl(contentList);
        //获取素材id集合
        List<Integer> materialIds = null;
        if(!CollectionUtils.isEmpty(imageUrlList)){
            //查询当前用户关联的素材id
            materialIds = getMaterialIds(userId,imageUrlList);
            //保存素材和文章关联关系
            wmNewsMaterialService.saveInfoBatch(wmNews.getId(),materialIds,0);
        }
        //保存文章封面和素材关联关系
        if(!CollectionUtils.isEmpty(imagesList)){
            //查询当前用户关联的素材id
            materialIds = getMaterialIds(userId,imagesList);
            //保存素材和文章关联关系
            wmNewsMaterialService.saveInfoBatch(wmNews.getId(),materialIds,1);
        }

        //如果不是保存草稿，生产文章自动审核消息
        if(!dto.getDraft()){
            kafkaTemplate.send(WM_NEWS_AUTO_SCAN_TOPIC,wmNews.getId().toString());
        }
    }

    @Override
    public void deleteById(Integer id) {
        //1、获取用户id，判断登录状态
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2、基于用户id和文章id查询文章数据
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getId,id).eq(WmNews::getWmUserId,userId);
        WmNews wmNews = this.getOne(queryWrapper);
        if(wmNews==null){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章数据不存在");
        }
        //获取文章状态
        Integer status = wmNews.getStatus();
        //已上架，且是发布状态不能删除
        if(status==9 && wmNews.getEnable()){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"已上架，且是发布状态文章不能删除");
        }
        //删除文章和素材关联数据
        wmNewsMaterialService.deleteByNewsId(id);
        //删除文章数据
        this.removeById(id);
    }

    @Override
    public void downOrUp(WmNewsDto wmNewsDto) {
        //1、获取用户id，判断登录状态
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2、基于用户id和文章id查询文章数据
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getId,wmNewsDto.getId()).eq(WmNews::getWmUserId,userId);
        WmNews wmNews = this.getOne(queryWrapper);
        if(wmNews==null){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章数据不存在");
        }
        //3、判断当前文章是否是发布状态
        if(wmNews.getStatus()!=9){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"未发布状态的文章不能上下架操作");
        }
        //4、更新文章上下架状态
        wmNews = new WmNews();
        wmNews.setId(wmNewsDto.getId());
        wmNews.setEnable(wmNewsDto.getEnable());
        this.updateById(wmNews);

        //5、更新自媒体文章的同时，更新article库中App文章上下架状态
        Map<String,Integer> map = new HashMap<>();
        map.put("wmNewsId",wmNewsDto.getId());
        map.put("enable",wmNewsDto.getEnable()?1:0);
        kafkaTemplate.send(WM_NEWS_UP_OR_DOWN_TOPIC,JsonUtils.toString(map));
    }

    @Override
    public void updateWmNews(WmNewsDto wmNewsDto) {
        WmNews wmNews = BeanHelper.copyProperties(wmNewsDto, WmNews.class);
        this.updateById(wmNews);
    }

    @Override
    public List<Integer> findWmNewsIds() {
        //查询审核通过待发布 8，并且发布时间小于当前时间文章id列表
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getStatus,WmNewsDto.Status.SUCCESS.getCode()).le(WmNews::getPublishTime,new Date());
        //执行查询
        List<WmNews> wmNewsList = this.list(queryWrapper);
        if(CollectionUtils.isEmpty(wmNewsList)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"待发布的自媒文章不存在");
        }
        List<Integer> ids = wmNewsList.stream().map(WmNews::getId).collect(Collectors.toList());
        return ids;
    }

    @Override
    public PageResult<WmNewsResultDTO> findList(NewsAuthDto dto) {
        //构建分页查询条件
        Page<WmNews> page = new Page<>(dto.getPage(),dto.getSize());
        //自定义SQL，进行多表关联查询 查询自媒体文章以及作者名称
        IPage<WmNewsResultDTO> iPage = this.getBaseMapper().slectWmNewsByPage(page,dto);
        if(CollectionUtils.isEmpty(iPage.getRecords())){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章列表不存在");
        }
        return new PageResult<>(dto.getPage(),dto.getSize(),iPage.getTotal(),iPage.getRecords());
    }

    private List<Integer> getMaterialIds(Integer userId, List<String> imageUrlList) {
        QueryWrapper<WmMaterial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmMaterial::getUserId,userId).in(WmMaterial::getUrl,imageUrlList);
        //执行查询
        List<WmMaterial> materialList = wmMaterialService.list(queryWrapper);
        //数据转换，获取素材id集合
        List<Integer> materialIds = materialList.stream().map(WmMaterial::getId).collect(Collectors.toList());
        return materialIds;
    }

    /**
     * 获取文章正文中素材地址列表
     * @param contentList
     * @return
     */
    private List<String> parseImageUrl(List<Map<String, String>> contentList) {
        //使用set集合去除重复的素材图片地址
        Set<String> set = new HashSet<>();
        for (Map<String, String> map : contentList) {
            //判断正文内容是否是image类型
            if("image".equals(map.get("type"))){
                //获取图片地址
                String imageUrl = map.get("value");
                set.add(imageUrl);
            }
        }
        //将set集合的数据全部存入list
        List<String> list = new ArrayList<>();
        list.addAll(set);
        return list;
    }
}
